package com.xjrsoft.module.system.controller;

import cn.dev33.satoken.session.SaSession;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.servlet.ServletUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.xjrsoft.common.annotation.XjrLog;
import com.xjrsoft.common.constant.GlobalConstant;
import com.xjrsoft.common.model.result.R;
import com.xjrsoft.common.page.ConventPage;
import com.xjrsoft.common.page.PageOutput;
import com.xjrsoft.common.utils.HttpContextUtils;
import com.xjrsoft.module.organization.entity.User;
import com.xjrsoft.module.system.dto.AddLogDto;
import com.xjrsoft.module.system.dto.LogExportDto;
import com.xjrsoft.module.system.dto.LogPageDto;
import com.xjrsoft.module.system.entity.Log;
import com.xjrsoft.module.system.service.ILogService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.io.ByteArrayOutputStream;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;

/**
 * <p>
 * 系统日志表 前端控制器
 * </p>
 *
 * @author tzx
 * @since 2022-03-04
 */
@RestController
@RequestMapping(GlobalConstant.SYSTEM_MODULE_PREFIX + "/log")
@Api(value = GlobalConstant.SYSTEM_MODULE_PREFIX + "/log",tags = "日志")
@AllArgsConstructor
public class LogController {

    private final ILogService logService;

    private static final Integer TODAY = 1;

    private static final Integer WEEK = 2;

    private static final Integer MONTH = 3;


    @GetMapping(value = "/page")
    @ApiOperation(value="日志列表(分页)")
    @XjrLog(value = "日志列表")
    public R page(@Valid LogPageDto dto){

        LambdaQueryWrapper<Log> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(StrUtil.isNotBlank(dto.getKeyword()),Log::getUsername,dto.getKeyword())
                .orderByDesc(Log::getCreateTime)
                .like(StrUtil.isNotBlank(dto.getKeyword()),Log::getIp,dto.getKeyword())
                .eq(dto.getCategory() > 0, Log::getCategory,dto.getCategory());

        if (ObjectUtil.isNotNull(dto.getCreateTimeStart()) && ObjectUtil.isNotNull(dto.getCreateTimeStart())) {
            queryWrapper.gt(Log::getCreateTime, LocalDateTimeUtil.beginOfDay(dto.getCreateTimeStart()));
            queryWrapper.lt(Log::getCreateTime, LocalDateTimeUtil.endOfDay(dto.getCreateTimeEnd()));
        }

        if(dto.getQueryType().equals(TODAY)){
            Date start = DateUtil.beginOfDay(new Date());
            Date end = DateUtil.endOfDay(new Date());
            queryWrapper.between(Log::getCreateTime, start,end);
        }

        if(dto.getQueryType().equals(WEEK)){
            DateTime start = DateUtil.beginOfWeek(new Date());
            DateTime end = DateUtil.endOfWeek(new Date());
            queryWrapper.between(Log::getCreateTime, start,end);
        }

        if(dto.getQueryType().equals(MONTH)){
            DateTime start = DateUtil.beginOfMonth(new Date());
            DateTime end = DateUtil.endOfMonth(new Date());
            queryWrapper.between(Log::getCreateTime, start, end);
        }

        IPage<Log> page = logService.page(ConventPage.getPage(dto), queryWrapper);
        PageOutput<Log> pageOutput = ConventPage.getPageOutput(page, Log.class);
        return R.ok(pageOutput);
    }


    @DeleteMapping("/all")
    @ApiOperation(value="清除所有日志")
    @XjrLog(value = "清除所有日志")
    public R clear(){
        return R.ok(logService.remove(new LambdaQueryWrapper<>()));
    }

    @DeleteMapping("/month")
    @ApiOperation(value="清除这个月的日志")
    @XjrLog(value = "清除这个月的日志")
    public R clearThisMonth(){
        DateTime start = DateUtil.beginOfMonth(new Date());
        DateTime end = DateUtil.endOfMonth(new Date());
        LambdaQueryWrapper<Log> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.between(Log::getCreateTime, start, end);
        return R.ok(logService.remove(queryWrapper));
    }

    @DeleteMapping("/week")
    @ApiOperation(value="清除这个周的日志")
    @XjrLog(value = "清除这个周的日志")
    public R clearThisWeek(){
        DateTime start = DateUtil.beginOfWeek(new Date());
        DateTime end = DateUtil.endOfWeek(new Date());
        LambdaQueryWrapper<Log> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.between(Log::getCreateTime, start, end);
        return R.ok(logService.remove(queryWrapper));
    }

    @DeleteMapping("/day")
    @ApiOperation(value="清除今天的日志")
    @XjrLog(value = "清除今天的日志")
    public R clearThisDay(){
        Date start = DateUtil.beginOfDay(new Date());
        Date end = DateUtil.endOfDay(new Date());
        LambdaQueryWrapper<Log> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.between(Log::getCreateTime, start, end);
        return R.ok(logService.remove(queryWrapper));
    }

    @DeleteMapping
    @ApiOperation(value="批量删除日志")
    @XjrLog(value = "批量删除日志")
    public R delete(@RequestBody List<Long> ids) {
        return R.ok(logService.removeBatchByIds(ids));
    }

    @DeleteMapping("/from")
    @ApiOperation(value="批量删除日志")
    @ApiImplicitParam("type: 0-保留近一周，1-保留近一个月，2-保留近三个月，3-不保留，全部删除")
    @XjrLog(value = "批量删除日志")
    public R deleteBy(@RequestParam Integer type) {
        LocalDateTime time = LocalDateTime.now();
        switch (type) {
            case 0:
                // 保留近一周
                time = time.plusWeeks(-1);
                break;
            case 1:
                // 保留近一个月
                time = time.plusMonths(-1);
                break;
            case 2:
                // 保留近三个月
                time = time.plusMonths(-3);
                break;
            case 3:
                // 不保留，全部删除
                break;
        }
        Wrapper<Log> wrapper =  Wrappers.<Log>query().lambda().lt(time != null, Log::getCreateTime, time);
        return R.ok(logService.remove(wrapper));
    }

    @PostMapping("/export")
    @ApiOperation(value="批量导出日志")
    @XjrLog(value = "批量导出日志")
    public ResponseEntity<byte[]> export(@RequestBody List<Long> ids) {
        List<Log> logList = logService.list(Wrappers.<Log>query().lambda().in(Log::getId, ids));
        ByteArrayOutputStream bot = new ByteArrayOutputStream();
        EasyExcel.write(bot, LogExportDto.class).excelType(ExcelTypeEnum.XLSX).sheet().doWrite(BeanUtil.copyToList(logList, LogExportDto.class));

        return R.fileStream(bot.toByteArray(), "系统日志" + ExcelTypeEnum.XLSX.getValue());
    }

    @PostMapping
    @ApiOperation(value="新增日志")
    @XjrLog(value = "新增日志")
    public R add(@RequestBody AddLogDto dto) {
        Log log = BeanUtil.toBean(dto, Log.class);
        log.setCreateTime(LocalDateTime.now());
        //获取request
        HttpServletRequest request = HttpContextUtils.getHttpServletRequest();
        //设置IP地址
        log.setIp(ServletUtil.getClientIP(request));
        // 添加操作人信息
        SaSession tokenSession = StpUtil.getTokenSession();
        User user = tokenSession.get(GlobalConstant.LOGIN_USER_INFO_KEY, new User());
        log.setUsername(user.getUserName());
        return R.ok(logService.save(log));
    }
}
